	
//******Steps to the redirection algorithm******
	//1) Send requests to the origin server.
	//2) Origin server replies with the DNS of the respective CDN.
	//3) Client sends a request to the HTTP Redirector.
	//4) HTTP Redirector adds the IP client in DNS
	//5) HTTP Redirector sends back to the Client. 
	//6) Client sends the DNS to the DNS Local.
	//7) DNS Local sends to the DNS authoritative
	//8) DNS Authoritative chooses the closest surrogate
	//9) DNS Authoritative sends the IP address of closest surrogate
	//10) Client starts the transfer process. 
//***************End****************************
	
package p2pcdnsim.cdn;

import p2pcdnsim.exception.PortAlreadyInUseException;
import p2pcdnsim.network.ApplicationProcess;
import p2pcdnsim.network.DatagramPacket;
import p2pcdnsim.network.DatagramSocket;
import p2pcdnsim.network.NetworkAddress;

public class RequestRedirector extends ApplicationProcess {

	private CDN cdn;
	private int nextSurrogate;
	
	public RequestRedirector(CDN cdn, String name) 
	{
		super(cdn.getModel(), name);
		this.cdn 		= cdn;
		nextSurrogate	= 0;
	}

	
	@Override
	protected void run() 
	{
		DatagramSocket socket = null;
		try {
			socket = this.createDatagramSocket(25);
		} catch (PortAlreadyInUseException e) {
			throw new RuntimeException(e);
		}
		
		while(true) {
			//System.out.println("["+this.currentTime()+"] RequestRedirector: Waiting for a datagram...");
			DatagramPacket packet = socket.receive();
			//DNSMessage content = (DNSMessage)packet.getMessage();
			//System.out.println("["+this.currentTime()+"] RequestRedirector: datagram received from "+packet.getSourceAddress()+": "+content);
			//System.out.println("["+this.currentTime()+"] RequestRedirector: sending response.");
			
			
			//**********Modification: Rafael*************

			
			
			DNSMessage response = new DNSMessage(chooseSurrogateShortestDistance(packet.getSourceAddress().getRouterAddress()).toString());
			
			
			packet = new DatagramPacket(socket.getAddress(),socket.getPort(),packet.getSourceAddress(),packet.getSourcedPort());
			packet.setMessage(response);
			socket.send(packet);		
		}
	}

	public NetworkAddress chooseSurrogateRoundRobin() {
		//Do a round robin based choice
		Surrogate chosen = cdn.getSurrogates().get((nextSurrogate++) % cdn.getSurrogates().size());
		return chosen.getNetworkAddress();
	}

	public NetworkAddress chooseSurrogateShortestDistance(NetworkAddress to) {
		int shortestDistance = Integer.MAX_VALUE;
		Surrogate chosen = null;
		for(Surrogate surrogate: cdn.getSurrogates()) {
			int distance = cdn.getSurrogateNode(surrogate).getNetworkLayer().getRouterTable().getDistance(to);
			//System.out.println("Surrogate "+surrogate.getId()+", distance to node "+to+": "+distance);
			if(distance < shortestDistance) {
				shortestDistance = distance;
				chosen = surrogate;
			}
		}
		//System.out.println("Surrogate chosen: "+chosen.getId());
		return chosen.getNetworkAddress();
	}
	

}
